﻿using System;
using System.Text;
using Mono.Cecil.Metadata;
using Mono.Collections.Generic;

namespace Mono.Cecil
{
	// Token: 0x020000D7 RID: 215
	internal class TypeParser
	{
		// Token: 0x060008A3 RID: 2211 RVA: 0x000053BC File Offset: 0x000035BC
		private TypeParser(string fullname)
		{
			this.fullname = fullname;
			this.length = fullname.Length;
		}

		// Token: 0x060008A4 RID: 2212 RVA: 0x00025274 File Offset: 0x00023474
		private TypeParser.Type ParseType(bool fq_name)
		{
			TypeParser.Type type = new TypeParser.Type();
			type.type_fullname = this.ParsePart();
			type.nested_names = this.ParseNestedNames();
			bool flag = TypeParser.TryGetArity(type);
			if (flag)
			{
				type.generic_arguments = this.ParseGenericArguments(type.arity);
			}
			type.specs = this.ParseSpecs();
			if (fq_name)
			{
				type.assembly = this.ParseAssemblyName();
			}
			return type;
		}

		// Token: 0x060008A5 RID: 2213 RVA: 0x000252E0 File Offset: 0x000234E0
		private static bool TryGetArity(TypeParser.Type type)
		{
			int num = 0;
			TypeParser.TryAddArity(type.type_fullname, ref num);
			string[] nested_names = type.nested_names;
			bool flag = !nested_names.IsNullOrEmpty<string>();
			if (flag)
			{
				for (int i = 0; i < nested_names.Length; i++)
				{
					TypeParser.TryAddArity(nested_names[i], ref num);
				}
			}
			type.arity = num;
			return num > 0;
		}

		// Token: 0x060008A6 RID: 2214 RVA: 0x00025344 File Offset: 0x00023544
		private static bool TryGetArity(string name, out int arity)
		{
			arity = 0;
			int num = name.LastIndexOf('`');
			bool flag = num == -1;
			return !flag && TypeParser.ParseInt32(name.Substring(num + 1), out arity);
		}

		// Token: 0x060008A7 RID: 2215 RVA: 0x00025380 File Offset: 0x00023580
		private static bool ParseInt32(string value, out int result)
		{
			return int.TryParse(value, out result);
		}

		// Token: 0x060008A8 RID: 2216 RVA: 0x0002539C File Offset: 0x0002359C
		private static void TryAddArity(string name, ref int arity)
		{
			int num;
			bool flag = !TypeParser.TryGetArity(name, out num);
			if (!flag)
			{
				arity += num;
			}
		}

		// Token: 0x060008A9 RID: 2217 RVA: 0x000253C4 File Offset: 0x000235C4
		private string ParsePart()
		{
			StringBuilder stringBuilder = new StringBuilder();
			while (this.position < this.length && !TypeParser.IsDelimiter(this.fullname[this.position]))
			{
				bool flag = this.fullname[this.position] == '\\';
				if (flag)
				{
					this.position++;
				}
				StringBuilder stringBuilder2 = stringBuilder;
				string text = this.fullname;
				int num = this.position;
				this.position = num + 1;
				stringBuilder2.Append(text[num]);
			}
			return stringBuilder.ToString();
		}

		// Token: 0x060008AA RID: 2218 RVA: 0x00025460 File Offset: 0x00023660
		private static bool IsDelimiter(char chr)
		{
			return "+,[]*&".IndexOf(chr) != -1;
		}

		// Token: 0x060008AB RID: 2219 RVA: 0x00025484 File Offset: 0x00023684
		private void TryParseWhiteSpace()
		{
			while (this.position < this.length && char.IsWhiteSpace(this.fullname[this.position]))
			{
				this.position++;
			}
		}

		// Token: 0x060008AC RID: 2220 RVA: 0x000254D0 File Offset: 0x000236D0
		private string[] ParseNestedNames()
		{
			string[] result = null;
			while (this.TryParse('+'))
			{
				TypeParser.Add<string>(ref result, this.ParsePart());
			}
			return result;
		}

		// Token: 0x060008AD RID: 2221 RVA: 0x00025504 File Offset: 0x00023704
		private bool TryParse(char chr)
		{
			bool flag = this.position < this.length && this.fullname[this.position] == chr;
			bool result;
			if (flag)
			{
				this.position++;
				result = true;
			}
			else
			{
				result = false;
			}
			return result;
		}

		// Token: 0x060008AE RID: 2222 RVA: 0x000053D9 File Offset: 0x000035D9
		private static void Add<T>(ref T[] array, T item)
		{
			array = array.Add(item);
		}

		// Token: 0x060008AF RID: 2223 RVA: 0x00025554 File Offset: 0x00023754
		private int[] ParseSpecs()
		{
			int[] result = null;
			while (this.position < this.length)
			{
				char c = this.fullname[this.position];
				char c2 = c;
				if (c2 != '&')
				{
					if (c2 != '*')
					{
						if (c2 != '[')
						{
							return result;
						}
						this.position++;
						char c3 = this.fullname[this.position];
						char c4 = c3;
						if (c4 != '*')
						{
							if (c4 != ']')
							{
								int num = 1;
								while (this.TryParse(','))
								{
									num++;
								}
								TypeParser.Add<int>(ref result, num);
								this.TryParse(']');
							}
							else
							{
								this.position++;
								TypeParser.Add<int>(ref result, -3);
							}
						}
						else
						{
							this.position++;
							TypeParser.Add<int>(ref result, 1);
						}
					}
					else
					{
						this.position++;
						TypeParser.Add<int>(ref result, -1);
					}
				}
				else
				{
					this.position++;
					TypeParser.Add<int>(ref result, -2);
				}
			}
			return result;
		}

		// Token: 0x060008B0 RID: 2224 RVA: 0x00025688 File Offset: 0x00023888
		private TypeParser.Type[] ParseGenericArguments(int arity)
		{
			TypeParser.Type[] array = null;
			bool flag = this.position == this.length || this.fullname[this.position] != '[';
			TypeParser.Type[] result;
			if (flag)
			{
				result = array;
			}
			else
			{
				this.TryParse('[');
				for (int i = 0; i < arity; i++)
				{
					bool flag2 = this.TryParse('[');
					TypeParser.Add<TypeParser.Type>(ref array, this.ParseType(flag2));
					bool flag3 = flag2;
					if (flag3)
					{
						this.TryParse(']');
					}
					this.TryParse(',');
					this.TryParseWhiteSpace();
				}
				this.TryParse(']');
				result = array;
			}
			return result;
		}

		// Token: 0x060008B1 RID: 2225 RVA: 0x00025730 File Offset: 0x00023930
		private string ParseAssemblyName()
		{
			bool flag = !this.TryParse(',');
			string result;
			if (flag)
			{
				result = string.Empty;
			}
			else
			{
				this.TryParseWhiteSpace();
				int num = this.position;
				while (this.position < this.length)
				{
					char c = this.fullname[this.position];
					bool flag2 = c == '[' || c == ']';
					if (flag2)
					{
						break;
					}
					this.position++;
				}
				result = this.fullname.Substring(num, this.position - num);
			}
			return result;
		}

		// Token: 0x060008B2 RID: 2226 RVA: 0x000257C8 File Offset: 0x000239C8
		public static TypeReference ParseType(ModuleDefinition module, string fullname, bool typeDefinitionOnly = false)
		{
			bool flag = string.IsNullOrEmpty(fullname);
			TypeReference result;
			if (flag)
			{
				result = null;
			}
			else
			{
				TypeParser typeParser = new TypeParser(fullname);
				result = TypeParser.GetTypeReference(module, typeParser.ParseType(true), typeDefinitionOnly);
			}
			return result;
		}

		// Token: 0x060008B3 RID: 2227 RVA: 0x00025800 File Offset: 0x00023A00
		private static TypeReference GetTypeReference(ModuleDefinition module, TypeParser.Type type_info, bool type_def_only)
		{
			TypeReference type;
			bool flag = !TypeParser.TryGetDefinition(module, type_info, out type);
			if (flag)
			{
				if (type_def_only)
				{
					return null;
				}
				type = TypeParser.CreateReference(type_info, module, TypeParser.GetMetadataScope(module, type_info));
			}
			return TypeParser.CreateSpecs(type, type_info);
		}

		// Token: 0x060008B4 RID: 2228 RVA: 0x00025844 File Offset: 0x00023A44
		private static TypeReference CreateSpecs(TypeReference type, TypeParser.Type type_info)
		{
			type = TypeParser.TryCreateGenericInstanceType(type, type_info);
			int[] specs = type_info.specs;
			bool flag = specs.IsNullOrEmpty<int>();
			TypeReference result;
			if (flag)
			{
				result = type;
			}
			else
			{
				for (int i = 0; i < specs.Length; i++)
				{
					switch (specs[i])
					{
					case -3:
						type = new ArrayType(type);
						break;
					case -2:
						type = new ByReferenceType(type);
						break;
					case -1:
						type = new PointerType(type);
						break;
					default:
					{
						ArrayType arrayType = new ArrayType(type);
						arrayType.Dimensions.Clear();
						for (int j = 0; j < specs[i]; j++)
						{
							arrayType.Dimensions.Add(default(ArrayDimension));
						}
						type = arrayType;
						break;
					}
					}
				}
				result = type;
			}
			return result;
		}

		// Token: 0x060008B5 RID: 2229 RVA: 0x00025920 File Offset: 0x00023B20
		private static TypeReference TryCreateGenericInstanceType(TypeReference type, TypeParser.Type type_info)
		{
			TypeParser.Type[] generic_arguments = type_info.generic_arguments;
			bool flag = generic_arguments.IsNullOrEmpty<TypeParser.Type>();
			TypeReference result;
			if (flag)
			{
				result = type;
			}
			else
			{
				GenericInstanceType genericInstanceType = new GenericInstanceType(type, generic_arguments.Length);
				Collection<TypeReference> genericArguments = genericInstanceType.GenericArguments;
				for (int i = 0; i < generic_arguments.Length; i++)
				{
					genericArguments.Add(TypeParser.GetTypeReference(type.Module, generic_arguments[i], false));
				}
				result = genericInstanceType;
			}
			return result;
		}

		// Token: 0x060008B6 RID: 2230 RVA: 0x0002598C File Offset: 0x00023B8C
		public static void SplitFullName(string fullname, out string @namespace, out string name)
		{
			int num = fullname.LastIndexOf('.');
			bool flag = num == -1;
			if (flag)
			{
				@namespace = string.Empty;
				name = fullname;
			}
			else
			{
				@namespace = fullname.Substring(0, num);
				name = fullname.Substring(num + 1);
			}
		}

		// Token: 0x060008B7 RID: 2231 RVA: 0x000259D0 File Offset: 0x00023BD0
		private static TypeReference CreateReference(TypeParser.Type type_info, ModuleDefinition module, IMetadataScope scope)
		{
			string @namespace;
			string name;
			TypeParser.SplitFullName(type_info.type_fullname, out @namespace, out name);
			TypeReference typeReference = new TypeReference(@namespace, name, module, scope);
			MetadataSystem.TryProcessPrimitiveTypeReference(typeReference);
			TypeParser.AdjustGenericParameters(typeReference);
			string[] nested_names = type_info.nested_names;
			bool flag = nested_names.IsNullOrEmpty<string>();
			TypeReference result;
			if (flag)
			{
				result = typeReference;
			}
			else
			{
				for (int i = 0; i < nested_names.Length; i++)
				{
					typeReference = new TypeReference(string.Empty, nested_names[i], module, null)
					{
						DeclaringType = typeReference
					};
					TypeParser.AdjustGenericParameters(typeReference);
				}
				result = typeReference;
			}
			return result;
		}

		// Token: 0x060008B8 RID: 2232 RVA: 0x00025A60 File Offset: 0x00023C60
		private static void AdjustGenericParameters(TypeReference type)
		{
			int num;
			bool flag = !TypeParser.TryGetArity(type.Name, out num);
			if (!flag)
			{
				for (int i = 0; i < num; i++)
				{
					type.GenericParameters.Add(new GenericParameter(type));
				}
			}
		}

		// Token: 0x060008B9 RID: 2233 RVA: 0x00025AA8 File Offset: 0x00023CA8
		private static IMetadataScope GetMetadataScope(ModuleDefinition module, TypeParser.Type type_info)
		{
			bool flag = string.IsNullOrEmpty(type_info.assembly);
			IMetadataScope result;
			if (flag)
			{
				result = module.TypeSystem.CoreLibrary;
			}
			else
			{
				AssemblyNameReference assemblyNameReference = AssemblyNameReference.Parse(type_info.assembly);
				AssemblyNameReference assemblyNameReference2;
				result = (module.TryGetAssemblyNameReference(assemblyNameReference, out assemblyNameReference2) ? assemblyNameReference2 : assemblyNameReference);
			}
			return result;
		}

		// Token: 0x060008BA RID: 2234 RVA: 0x00025AF4 File Offset: 0x00023CF4
		private static bool TryGetDefinition(ModuleDefinition module, TypeParser.Type type_info, out TypeReference type)
		{
			type = null;
			bool flag = !TypeParser.TryCurrentModule(module, type_info);
			bool result;
			if (flag)
			{
				result = false;
			}
			else
			{
				TypeDefinition typeDefinition = module.GetType(type_info.type_fullname);
				bool flag2 = typeDefinition == null;
				if (flag2)
				{
					result = false;
				}
				else
				{
					string[] nested_names = type_info.nested_names;
					bool flag3 = !nested_names.IsNullOrEmpty<string>();
					if (flag3)
					{
						for (int i = 0; i < nested_names.Length; i++)
						{
							TypeDefinition nestedType = typeDefinition.GetNestedType(nested_names[i]);
							bool flag4 = nestedType == null;
							if (flag4)
							{
								return false;
							}
							typeDefinition = nestedType;
						}
					}
					type = typeDefinition;
					result = true;
				}
			}
			return result;
		}

		// Token: 0x060008BB RID: 2235 RVA: 0x00025B8C File Offset: 0x00023D8C
		private static bool TryCurrentModule(ModuleDefinition module, TypeParser.Type type_info)
		{
			bool flag = string.IsNullOrEmpty(type_info.assembly);
			bool result;
			if (flag)
			{
				result = true;
			}
			else
			{
				bool flag2 = module.assembly != null && module.assembly.Name.FullName == type_info.assembly;
				result = flag2;
			}
			return result;
		}

		// Token: 0x060008BC RID: 2236 RVA: 0x00025BE0 File Offset: 0x00023DE0
		public static string ToParseable(TypeReference type, bool top_level = true)
		{
			bool flag = type == null;
			string result;
			if (flag)
			{
				result = null;
			}
			else
			{
				StringBuilder stringBuilder = new StringBuilder();
				TypeParser.AppendType(type, stringBuilder, true, top_level);
				result = stringBuilder.ToString();
			}
			return result;
		}

		// Token: 0x060008BD RID: 2237 RVA: 0x00025C14 File Offset: 0x00023E14
		private static void AppendNamePart(string part, StringBuilder name)
		{
			foreach (char c in part)
			{
				bool flag = TypeParser.IsDelimiter(c);
				if (flag)
				{
					name.Append('\\');
				}
				name.Append(c);
			}
		}

		// Token: 0x060008BE RID: 2238 RVA: 0x00025C5C File Offset: 0x00023E5C
		private static void AppendType(TypeReference type, StringBuilder name, bool fq_name, bool top_level)
		{
			TypeReference elementType = type.GetElementType();
			TypeReference declaringType = elementType.DeclaringType;
			bool flag = declaringType != null;
			if (flag)
			{
				TypeParser.AppendType(declaringType, name, false, top_level);
				name.Append('+');
			}
			string @namespace = type.Namespace;
			bool flag2 = !string.IsNullOrEmpty(@namespace);
			if (flag2)
			{
				TypeParser.AppendNamePart(@namespace, name);
				name.Append('.');
			}
			TypeParser.AppendNamePart(elementType.Name, name);
			bool flag3 = !fq_name;
			if (!flag3)
			{
				bool flag4 = type.IsTypeSpecification();
				if (flag4)
				{
					TypeParser.AppendTypeSpecification((TypeSpecification)type, name);
				}
				bool flag5 = TypeParser.RequiresFullyQualifiedName(type, top_level);
				if (flag5)
				{
					name.Append(", ");
					name.Append(TypeParser.GetScopeFullName(type));
				}
			}
		}

		// Token: 0x060008BF RID: 2239 RVA: 0x00025D18 File Offset: 0x00023F18
		private static string GetScopeFullName(TypeReference type)
		{
			IMetadataScope scope = type.Scope;
			MetadataScopeType metadataScopeType = scope.MetadataScopeType;
			MetadataScopeType metadataScopeType2 = metadataScopeType;
			string fullName;
			if (metadataScopeType2 != MetadataScopeType.AssemblyNameReference)
			{
				if (metadataScopeType2 != MetadataScopeType.ModuleDefinition)
				{
					throw new ArgumentException();
				}
				fullName = ((ModuleDefinition)scope).Assembly.Name.FullName;
			}
			else
			{
				fullName = ((AssemblyNameReference)scope).FullName;
			}
			return fullName;
		}

		// Token: 0x060008C0 RID: 2240 RVA: 0x00025D70 File Offset: 0x00023F70
		private static void AppendTypeSpecification(TypeSpecification type, StringBuilder name)
		{
			bool flag = type.ElementType.IsTypeSpecification();
			if (flag)
			{
				TypeParser.AppendTypeSpecification((TypeSpecification)type.ElementType, name);
			}
			ElementType etype = type.etype;
			ElementType elementType = etype;
			switch (elementType)
			{
			case ElementType.Ptr:
				name.Append('*');
				return;
			case ElementType.ByRef:
				name.Append('&');
				return;
			case ElementType.ValueType:
			case ElementType.Class:
			case ElementType.Var:
				return;
			case ElementType.Array:
				break;
			case ElementType.GenericInst:
			{
				GenericInstanceType genericInstanceType = (GenericInstanceType)type;
				Collection<TypeReference> genericArguments = genericInstanceType.GenericArguments;
				name.Append('[');
				for (int i = 0; i < genericArguments.Count; i++)
				{
					bool flag2 = i > 0;
					if (flag2)
					{
						name.Append(',');
					}
					TypeReference typeReference = genericArguments[i];
					bool flag3 = typeReference.Scope != typeReference.Module;
					bool flag4 = flag3;
					if (flag4)
					{
						name.Append('[');
					}
					TypeParser.AppendType(typeReference, name, true, false);
					bool flag5 = flag3;
					if (flag5)
					{
						name.Append(']');
					}
				}
				name.Append(']');
				return;
			}
			default:
				if (elementType != ElementType.SzArray)
				{
					return;
				}
				break;
			}
			ArrayType arrayType = (ArrayType)type;
			bool isVector = arrayType.IsVector;
			if (isVector)
			{
				name.Append("[]");
			}
			else
			{
				name.Append('[');
				for (int j = 1; j < arrayType.Rank; j++)
				{
					name.Append(',');
				}
				name.Append(']');
			}
		}

		// Token: 0x060008C1 RID: 2241 RVA: 0x00025EFC File Offset: 0x000240FC
		private static bool RequiresFullyQualifiedName(TypeReference type, bool top_level)
		{
			bool flag = type.Scope == type.Module;
			bool result;
			if (flag)
			{
				result = false;
			}
			else
			{
				bool flag2 = type.Scope.Name == "mscorlib" && top_level;
				result = !flag2;
			}
			return result;
		}

		// Token: 0x04000343 RID: 835
		private readonly string fullname;

		// Token: 0x04000344 RID: 836
		private readonly int length;

		// Token: 0x04000345 RID: 837
		private int position;

		// Token: 0x020000D8 RID: 216
		private class Type
		{
			// Token: 0x04000346 RID: 838
			public const int Ptr = -1;

			// Token: 0x04000347 RID: 839
			public const int ByRef = -2;

			// Token: 0x04000348 RID: 840
			public const int SzArray = -3;

			// Token: 0x04000349 RID: 841
			public string type_fullname;

			// Token: 0x0400034A RID: 842
			public string[] nested_names;

			// Token: 0x0400034B RID: 843
			public int arity;

			// Token: 0x0400034C RID: 844
			public int[] specs;

			// Token: 0x0400034D RID: 845
			public TypeParser.Type[] generic_arguments;

			// Token: 0x0400034E RID: 846
			public string assembly;
		}
	}
}
